import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import javax.swing.JButton;

/**
 * A ButtonGrid is an extension of the JPanel which is comprised of 100 JButtons
 * in a grid layout. The ButtonGrid listens for clicks on each button and may
 * have its contents highlighted.
 * 
 * @author Vo, Wu, and Wyan.
 * 
 */

public class ButtonGrid extends JPanel {

	/**
	 * The size of the grid.
	 */
	private static final int SIZE = 10;

	/**
	 * The size of the grid, both height and width.
	 */
	private static final int GRID_SIZE = 400;

	/**
	 * The size of the buttons, both height and width.
	 */
	private static final int BUTTON_SIZE = 50;

	/**
	 * The width of borders used for highlighting cells.
	 */
	private static final int BORDER_WIDTH = 3;

	/**
	 * The JPanel on which all components will be placed.
	 */
	private JPanel frame = new JPanel();

	/**
	 * The two dimensional array of JButtons, using the array indices to
	 * identify the buttons coordinate.
	 */
	private JButton[][] grid; // names the grid of buttons

	/**
	 * The label of the most recently clicked button.
	 */
	private String clickedButton = "";

	/**
	 * Default constructor of the ButtonGrid creates a square grid of length
	 * SIZE. Preferences of the frame are set and each button is standardized
	 * before being added to the frame.
	 */
	public ButtonGrid() { // constructor
		frame.setLayout(new GridLayout(SIZE, SIZE)); // set layout
		grid = new JButton[SIZE][SIZE]; // allocate the size of grid
		this.setPreferredSize(new Dimension(GRID_SIZE, GRID_SIZE));
		this.setMinimumSize(new Dimension(GRID_SIZE, GRID_SIZE));
		this.setMaximumSize(new Dimension(GRID_SIZE, GRID_SIZE));
		for (int x = 0; x < SIZE; x++) {
			for (int y = 0; y < SIZE; y++) {
				char c = (char) (x + 65);
				grid[x][y] = new JButton("" + c + (y + 1)); // creates new
															// button
				grid[x][y].setPreferredSize(new Dimension(BUTTON_SIZE,
						BUTTON_SIZE));
				grid[x][y].setMaximumSize(new Dimension(BUTTON_SIZE,
						BUTTON_SIZE));
				grid[x][y].setMinimumSize(new Dimension(BUTTON_SIZE,
						BUTTON_SIZE));
				grid[x][y].setBackground(Color.gray);
				grid[x][y].setBorder(BorderFactory
						.createLineBorder(Color.black));
				grid[x][y].setOpaque(true);
				frame.add("" + c + (y + 1), grid[x][y]); // adds button to grid
			}
		}
		frame.setVisible(true); // makes frame visible
	}

	/**
	 * @return Returns the frame holding the components.
	 */
	public final JPanel getFrame() {
		return this.frame;
	}

	/**
	 * An action listener is added to each JButton within the ButtonGrid.
	 * 
	 * @param click
	 *            The listener being added to the button.
	 */
	public final void addActionListener(ActionListener click) {
		for (int x = 0; x < SIZE; x++) {
			for (int y = 0; y < SIZE; y++) {
				grid[x][y].addActionListener(click);
			}
		}
	}

	/**
	 * Loops through the buttons of the ButtonGrid and enables each one.
	 */
	public final void enableButtons() {
		for (int x = 0; x < SIZE; x++) {
			for (int y = 0; y < SIZE; y++) {
				grid[x][y].setEnabled(true);
			}
		}
	}

	/**
	 * Loops through the buttons of the ButtonGrid and disables each one.
	 */
	public final void disableButtons() {
		for (int x = 0; x < SIZE; x++) {
			for (int y = 0; y < SIZE; y++) {
				grid[x][y].setEnabled(false);
			}
		}
	}

	/**
	 * @return The label of the button clicked on the ButtonGrid.
	 */
	public final String getClickedCell() {
		return this.clickedButton;
	}

	/**
	 * Highlights the button corresponding to the cell location parameter.
	 * 
	 * @param cell
	 *            The cell that will be highlighted, given in <int,int> String
	 *            format.
	 * @requires The contents of cell contains only integers. The String must be
	 *           able to be resolved into two coordinates ranging from 1-10.
	 */
	public final void highlightCell(String cell) {
		int y = 0;
		int x = 0;
		if (cell.length() > 2 && cell.charAt(1) == '0') {
			x = Integer.valueOf(cell.substring(0, 2)) - 1;
		} else {
			x = Character.getNumericValue(cell.charAt(0)) - 1;
		}
		if (cell.length() == 2) {
			y = Character.getNumericValue(cell.charAt(1)) - 1;
		} else {
			y = Integer.valueOf(cell.substring(1)) - 1;
		}
		grid[x][y].setBorder(BorderFactory.createLineBorder(Color.GREEN,
				BORDER_WIDTH));
		grid[x][y].setForeground(Color.green);
		grid[x][y].setOpaque(true);
	}

	/**
	 * Removes the highlight effect from the selected cell.
	 * 
	 * @param cell
	 *            The cell whose highlight will be removed, given in <int,int>
	 *            String format.
	 * @requires The contents of cell contains only integers. The String must be
	 *           able to be resolved into two coordinates ranging from 1-10.
	 */
	public final void dehighlightCell(String cell) {
		int y = 0;
		int x = 0;
		if (cell.length() > 2 && cell.charAt(1) == '0') {
			x = Integer.valueOf(cell.substring(0, 2)) - 1;
		} else {
			x = Character.getNumericValue(cell.charAt(0)) - 1;
		}
		if (cell.length() == 2) {
			y = Character.getNumericValue(cell.charAt(1)) - 1;
		} else {
			y = Integer.valueOf(cell.substring(1)) - 1;
		}
		grid[x][y].setBackground(Color.gray);
		grid[x][y].setForeground(Color.black);
		grid[x][y].setBorder(BorderFactory.createLineBorder(Color.black));
		grid[x][y].setOpaque(true);
	}

	/**
	 * Changes the selected cell's highlight to the specified color.
	 * 
	 * @param cell
	 *            The cell that will be highlighted, given in <char,int> String
	 *            format.
	 * @param color
	 *            The key given to determine what color the selected cell will
	 *            highlight to.
	 * @requires The contents of the cell must contain a sequence of a character
	 *           A-J followed by an integer 0-10.
	 */
	public final void changeColor(String cell, String color) {
		int y = 0;
		int x = 0;
		if (cell.length() > 2 && cell.charAt(1) == '0') {
			x = Integer.valueOf(cell.substring(0, 2)) - 1;
		} else {
			x = Character.getNumericValue(cell.charAt(0)) - 10;
		}
		if (cell.length() == 2) {
			y = Character.getNumericValue(cell.charAt(1)) - 1;
		} else {
			y = Integer.valueOf(cell.substring(1)) - 1;
		}
		if (color.equals("HIT")) {
			grid[x][y].setBorder(BorderFactory.createLineBorder(Color.RED,
					BORDER_WIDTH));
			grid[x][y].setForeground(Color.RED);
			grid[x][y].setOpaque(true);
		} else if (color.equals("MISS")) {
			grid[x][y].setBorder(BorderFactory.createLineBorder(Color.WHITE,
					BORDER_WIDTH));
			grid[x][y].setForeground(Color.WHITE);
			grid[x][y].setOpaque(true);
		} else if (color.equals("SUNK")) {
			grid[x][y].setBorder(BorderFactory.createLineBorder(Color.ORANGE,
					BORDER_WIDTH));
			grid[x][y].setForeground(Color.ORANGE);
			grid[x][y].setOpaque(true);
		} else if (color.equals("REMAINING")) {
			grid[x][y].setBorder(BorderFactory.createLineBorder(Color.GREEN,
					BORDER_WIDTH));
			grid[x][y].setForeground(Color.GREEN);
			grid[x][y].setOpaque(true);
		}
	}
}
